package com.carryking.smart.rpc.utils;

import com.carryking.smart.rpc.RemoteServiceRepository;
import com.carryking.smart.rpc.constant.RespStatusConstant;
import com.carryking.smart.rpc.entity.RequestEntity;
import com.carryking.smart.rpc.entity.ResponseEntity;
import com.carryking.smart.rpc.entity.ResponseFuture;
import com.carryking.smart.rpc.netty.CustomerChannelInitializer;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;

/**
 * Created by jincarry on 2018/1/10.
 */
@Slf4j
public class RequestUtils {

    private static EventLoopGroup group = new NioEventLoopGroup();

    public static Bootstrap getBootstrap() {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .handler(new CustomerChannelInitializer());
        return bootstrap;
    }

    public static ResponseEntity send(String ip, int port,int timeOut, RequestEntity requestEntity) throws InterruptedException {
        final CountDownLatch latch = new CountDownLatch(2); //第一次完成是请求成功发送 第二次是成功接收到响应
        final ResponseFuture responseFuture = new ResponseFuture(latch,timeOut);

        RemoteServiceRepository.set(requestEntity.getRequestId(),responseFuture);

        ChannelFuture channelFuture = getBootstrap().connect(ip, port).sync();
        channelFuture.channel().writeAndFlush(requestEntity).addListener(new ChannelFutureListener() {
            public void operationComplete(ChannelFuture future) throws Exception {
                latch.countDown();
            }
        });
        try {
            ResponseEntity responseEntity =  responseFuture.get();
            RemoteServiceRepository.remove(requestEntity.getRequestId());
            return responseEntity;
        } catch (Exception e) {
            log.info("获取消息时发生异常");
            ResponseEntity responseEntity = new ResponseEntity();
            responseEntity.setCode(RespStatusConstant.TIME_OUT);
            responseEntity.setRequestId(requestEntity.getRequestId());
            return responseEntity;
        }
    }


}
